﻿using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.Repositories;
using HiShing.TongDanGuanJia.Devices.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HiShing.TongDanGuanJia.Devices
{
    public class DeviceAppService : AsyncCrudAppService<Device, DeviceDto, string, PagedDeviceResultRequestDto, CreateDeviceDto, UpdateDeviceDto>, IDeviceAppService
    {
        IRepository<UserDevice, int> _userDeviceRepository;
        public DeviceAppService(IRepository<Device, string> repository, IRepository<UserDevice, int> userDeviceRepository) : base(repository)
        {
            _userDeviceRepository = userDeviceRepository;
        }
        public override async Task<DeviceDto> CreateAsync(CreateDeviceDto input)
        {
            return await Task.Run(() =>
            {
                var entity = new Device();
                entity.RegisterTime = DateTime.Now;
                entity.DeviceId = input.DeviceId;
                entity.ProductKey = input.ProductKey;
                entity.DeviceTypeId = input.DeviceTypeId;
                entity.DisplayName = input.DisplayName;
                entity.Id = input.DeviceId;
                Repository.InsertAsync(entity);
                return MapToEntityDto(entity);
            });
        }

        public override async Task<DeviceDto> UpdateAsync(UpdateDeviceDto input)
        {
            return await Task.Run(() =>
            {
                var entity = Repository.Get(input.DeviceId);
                entity.ProductKey = input.ProductKey;
                entity.DeviceTypeId = input.DeviceTypeId;
                entity.DisplayName = input.DisplayName;
                Repository.Update(entity);

                return MapToEntityDto(entity);
            });
        }

        public override async Task<PagedResultDto<DeviceDto>> GetAllAsync(PagedDeviceResultRequestDto input)
        {
            return await Task.Run(() =>
            {
                var query = _userDeviceRepository.GetAllIncluding(d => d.Device);

                //if (!managerUserIds.Contains(input.UserId))
                //{
                    query = query.Where(d => d.UserId == input.UserId);
                //}
                if (input.DeviceTypeId.HasValue)
                {
                    query = query.Where(d => d.Device.DeviceTypeId == input.DeviceTypeId);
                }

                var deviceQuery = query.Select(d => d.Device).Distinct();
                var totalCount = deviceQuery.Count();

                var entities = deviceQuery.OrderBy(d => d.DeviceId).Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

                return new PagedResultDto<DeviceDto>(
                    totalCount,
                    entities.Select(MapToEntityDto).ToList()
                );
            });
        }


        public override Task DeleteAsync(EntityDto<string> input)
        {
            _userDeviceRepository.Delete(d => d.DeviceId == input.Id);

            Repository.Delete(input.Id);
            return Task.CompletedTask;
        }


        /// <summary>
        /// 更改设备编号
        /// </summary>
        /// <param name="originalDeviceId"></param>
        /// <param name="newDeviceId"></param>
        /// <returns></returns>
        public async Task<DeviceDto> ChangeDeviceId(string originalDeviceId, string newDeviceId)
        {
            return await Task.Run(() =>
            {
                var userIds = _userDeviceRepository.GetAll().Where(d => d.DeviceId == originalDeviceId).Select(d => d.UserId).ToList();
                _userDeviceRepository.Delete(d => d.DeviceId == originalDeviceId);


                var entity = Repository.Get(originalDeviceId);
                entity.DeviceId = newDeviceId;
                entity.Id = newDeviceId;
                Repository.UpdateAsync(entity);

                var userDevices = new List<UserDevice>();
                foreach (var userId in userIds)
                {
                    userDevices.Add(new UserDevice { DeviceId = newDeviceId, UserId = userId });
                }

                return MapToEntityDto(entity);
            });
        }

        /// <summary>
        /// 注意，会删除此设备的所有不在用户列表中的用户信息
        /// </summary>
        /// <param name="deviceId"></param>
        /// <param name="userIds"></param>
        /// <returns></returns>
        public async Task<bool> ChangeDeviceUsers(string deviceId, string userIds)
        {
            return await Task.Run(() =>
             {
                 var ids = userIds.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToList();

                 _userDeviceRepository.Delete(d => d.DeviceId == deviceId);

                 var userDevices = new List<UserDevice>();
                 foreach (var userId in ids)
                 {
                     userDevices.Add(new UserDevice { DeviceId = deviceId, UserId = userId });
                 }

                 _userDeviceRepository.InsertRange(userDevices);

                 return true;
             });
        }

    }
}
